// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

module A_cse_ocs_dpa_aes10c_gf16_inv_masked
  #(
     parameter OCS_AES_DPA_USE_CTECH = 1,
     parameter POLY1 = 3
   )
  (
   input logic [3:0] a,
   input logic [3:0] a_mask,
   input logic [3:0] o_mask,
   input logic [3:0] temp_mask,
   output logic [3:0] o 
  );
   
   // internal signals
   wire [3:0] a_2, a_4, a_8;
   wire [3:0] a_mask_2, a_mask_4, a_mask_8;
   wire [3:0] a_8_remasked, a_10_remasked;
   wire [3:0] a_8_mask;

   // Inverse computation in GF(16)
   // Powers of in and a_mask
   A_cse_ocs_dpa_aes10c_gf16_pows #(.POLY1(POLY1)) a_pows0
     (
      .a   (a),
      .a_2 (a_2),
      .a_4 (a_4),
      .a_8 (a_8)
     );

   A_cse_ocs_dpa_aes10c_gf16_pows #(.POLY1(POLY1)) mask_pows0
     (
      .a   (a_mask),
      .a_2 (a_mask_2),
      .a_4 (a_mask_4),
      .a_8 (a_mask_8)
     );

   // Combinational logic to compute inverse
   // Compute a^10 using a masked multiplication
   // Need to refresh mask of a^8 (as it is linearly dependent on mask of a^2)
   assign a_8_remasked = a_8 ^ o_mask;
   assign a_8_mask = a_mask_8 ^ o_mask;

   A_cse_ocs_dpa_aes10c_gf16_mul_masked
    #(.OCS_AES_DPA_USE_CTECH(OCS_AES_DPA_USE_CTECH),
      .POLY1(POLY1))
   mul_masked0
    (
      .a (a_2),
      .a_mask (a_mask_2),
      .b (a_8_remasked),
      .b_mask (a_8_mask),
      .o_mask (temp_mask),
      .o (a_10_remasked)
    );

    A_cse_ocs_dpa_aes10c_gf16_mul_masked
    #(.OCS_AES_DPA_USE_CTECH(OCS_AES_DPA_USE_CTECH),
      .POLY1(POLY1))
    mul_masked1
    (
      .a (a_4),
      .a_mask (a_mask_4),
      .b (a_10_remasked),
      .b_mask (temp_mask),
      .o_mask (o_mask),
      .o (o)
    );

endmodule
